﻿using System;
using UnityEngine;

static class MonoSingletonInternal
{
    public const string MountNodeName = "MonoSingleton";

    public static Transform mountParentTrans = null;

    public static Transform DontDestroyOnLoadParent
    {
        get
        {
            if (mountParentTrans == null)
            {
                GameObject go = new GameObject(MountNodeName);
                mountParentTrans = go.transform;
                UnityEngine.Object.DontDestroyOnLoad(go);
            }

            return mountParentTrans;
        }
    }
}

public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static GameObject mountNode = null;

    /// <summary>
    /// 单例
    /// </summary>
    protected static T instance = null;

    /// <summary>
    /// 初始化
    /// </summary>
    private bool inited = false;

    /// <summary>
    /// 获取单例
    /// </summary>
    public static T Instance
    {
        get { return instance ?? (instance = CreateSingleton()); }
    }

    /// <summary>
    /// 获得单件
    /// </summary>
    public static T GetSingleton()
    {
        return instance ?? (instance = CreateSingleton());
    }

    private static T CreateSingleton()
    {
        T t = FindObjectOfType<T>();

        if (t == null)
        {
            if (mountNode == null)
            {
                mountNode = new GameObject(typeof(T).Name);
            }

            t = mountNode.AddComponent<T>();
        }

        return t;
    }

    private void Awake()
    {
        if (instance != null && instance != this)
        {
            enabled = false;
            Debug.Log("MonoSingleton只允许存在一个");
        }
        else if (!inited)
        {
            inited = true;
            instance = this as T;
            if (transform.parent == null)
            {
                transform.SetParent(MonoSingletonInternal.DontDestroyOnLoadParent);
            }

            Initialize();
        }
    }

    public static void SafeRelease()
    {
        if (instance == null)
        {
            return;
        }

        instance.Release();
    }

    public virtual void Initialize()
    {

    }

    public virtual void Release()
    {
        instance = null;
        if (mountNode != null)
        {
            DestroyImmediate(mountNode);
        }
    }

    protected void OnDestory()
    {
        instance = null;
    }
}
